package com.fulu.game.bi.service.impl.room;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.fulu.game.bi.common.util.csv.CsvExportUtil;
import com.fulu.game.bi.common.util.csv.Mapper;
import com.fulu.game.bi.common.util.csv.Querier;
import com.fulu.game.bi.common.util.lang.StringUtils;
import com.fulu.game.bi.entity.bo.channel.VoiceOverviewListBO;
import com.fulu.game.bi.entity.bo.channel.VoiceRealTimeBO;
import com.fulu.game.bi.entity.dto.VoiceOverviewListDTO;
import com.fulu.game.bi.entity.enums.QueryTypeStatusEnum;
import com.fulu.game.bi.entity.vo.room.RoomStatAllUserDayRealTimeVO;
import com.fulu.game.bi.entity.vo.room.VoiceOverviewVO;
import com.fulu.game.bi.entity.vo.common.CodeNameVO;
import com.fulu.game.bi.hbase.HBaseRoomStatAllUserDAO;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Slf4j
public class VoiceOverviewService extends BaseVoiceService {
    @Autowired
    private HBaseRoomStatAllUserDAO hBaseRoomStatAllUserDAO;
    @Autowired
    private RoomConditionService roomConditionService;

    public List<RoomStatAllUserDayRealTimeVO> overviewRealTime() {
        VoiceRealTimeBO voiceRealTimeBO = new VoiceRealTimeBO();
        voiceRealTimeBO.setStatDate(DateUtil.today());
        RoomStatAllUserDayRealTimeVO today = hBaseRoomStatAllUserDAO.findByParameter(voiceRealTimeBO);
        voiceRealTimeBO.setStatDate(DateUtil.formatDate(DateUtil.offsetDay(new Date(), -1)));
        RoomStatAllUserDayRealTimeVO yesterday = hBaseRoomStatAllUserDAO.findByParameter(voiceRealTimeBO);
        voiceRealTimeBO.setStatDate(DateUtil.formatDate(DateUtil.offsetDay(new Date(), -2)));
        RoomStatAllUserDayRealTimeVO theDayBeforeYesterday = hBaseRoomStatAllUserDAO.findByParameter(voiceRealTimeBO);
        voiceRealTimeBO.setStatDate(DateUtil.formatDate(DateUtil.offsetDay(new Date(), -8)));
        RoomStatAllUserDayRealTimeVO lastWeekYesterdaySameDay = hBaseRoomStatAllUserDAO.findByParameter(voiceRealTimeBO);
        List<RoomStatAllUserDayRealTimeVO> list = new ArrayList<>();
        yesterday.setVirtualMoneyAllDay(datio(yesterday.getVirtualMoneyAll(), theDayBeforeYesterday.getVirtualMoneyAll()));
        yesterday.setVirtualMoneyAllWeek(datio(yesterday.getVirtualMoneyAll(), lastWeekYesterdaySameDay.getVirtualMoneyAll()));
        yesterday.setConsumeUserNumDay(datio(yesterday.getConsumeUserNum(), theDayBeforeYesterday.getConsumeUserNum()));
        yesterday.setConsumeUserNumWeek(datio(yesterday.getConsumeUserNum(), lastWeekYesterdaySameDay.getConsumeUserNum()));
        yesterday.setConsumeNumDay(datio(yesterday.getConsumeNum(), theDayBeforeYesterday.getConsumeNum()));
        yesterday.setConsumeNumWeek(datio(yesterday.getConsumeNum(), lastWeekYesterdaySameDay.getConsumeNum()));
        yesterday.setLivelyRoomNumDay(datio(yesterday.getLivelyRoomNum(), theDayBeforeYesterday.getLivelyRoomNum()));
        yesterday.setLivelyRoomNumWeek(datio(yesterday.getLivelyRoomNum(), lastWeekYesterdaySameDay.getLivelyRoomNum()));
        yesterday.setEnterRoomUserNumDay(datio(yesterday.getEnterRoomUserNum(), theDayBeforeYesterday.getEnterRoomUserNum()));
        yesterday.setEnterRoomUserNumWeek(datio(yesterday.getEnterRoomUserNum(), lastWeekYesterdaySameDay.getEnterRoomUserNum()));
        yesterday.setStayFiveMinUserNumDay(datio(yesterday.getStayFiveMinUserNum(), theDayBeforeYesterday.getStayFiveMinUserNum()));
        yesterday.setStayFiveMinUserNumWeek(datio(yesterday.getStayFiveMinUserNum(), lastWeekYesterdaySameDay.getStayFiveMinUserNum()));
        yesterday.setInteractUserNumDay(datio(yesterday.getInteractUserNum(), theDayBeforeYesterday.getInteractUserNum()));
        yesterday.setInteractUserNumWeek(datio(yesterday.getInteractUserNum(), lastWeekYesterdaySameDay.getInteractUserNum()));
        yesterday.setUserStayTimeAvgDay(datio(yesterday.getUserStayTimeAvg(), theDayBeforeYesterday.getUserStayTimeAvg()));
        yesterday.setUserStayTimeAvgWeek(datio(yesterday.getUserStayTimeAvg(), lastWeekYesterdaySameDay.getUserStayTimeAvg()));
        list.add(today);
        list.add(yesterday);
        return list;
    }

    private BigDecimal datio(BigDecimal a, BigDecimal b) {
        if (Objects.isNull(b) || b.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        }
        return a.subtract(b).divide(b, 2, BigDecimal.ROUND_HALF_DOWN);
    }

    public List<VoiceOverviewVO> list(VoiceOverviewListDTO voiceOverviewListDTO) {
        VoiceOverviewListBO voiceOverviewListBO = new VoiceOverviewListBO();
        BeanUtil.copyProperties(voiceOverviewListDTO, voiceOverviewListBO);
        voiceOverviewListBO.setDataFromStr(voiceOverviewListDTO.getDataFrom() == null ? null : voiceOverviewListDTO.getDataFrom() + "");
        voiceOverviewListBO.setRoomCategoryIdStr(voiceOverviewListDTO.getRoomCategoryId() == null ? null : voiceOverviewListDTO.getRoomCategoryId() + "");
        if (StringUtils.isEmpty(voiceOverviewListBO.getRoomCategoryIdStr())) {
            voiceOverviewListBO.setTableName(tableNameMapForALlCategory.get(voiceOverviewListDTO.getQueryType()));
        } else {
            voiceOverviewListBO.setTableName(tableNameMapForCategory.get(voiceOverviewListDTO.getQueryType()));
        }
        List<VoiceOverviewVO> list = hBaseRoomStatAllUserDAO.overviewList(voiceOverviewListBO);
        List<CodeNameVO> roomCategories = roomConditionService.roomCategory();
        Map<String, String> roomCategoriesMap = roomCategories.stream().collect(Collectors.toMap(CodeNameVO::getCode, CodeNameVO::getName));
        return list.stream().map(map -> {
            QueryTypeStatusEnum anEnum = QueryTypeStatusEnum.getEnum(voiceOverviewListDTO.getQueryType());
            switch (anEnum) {
                case DAY:
                    map.setStartDate(map.getStatDate());
                    map.setEndDate(map.getStatDate());
                    break;
                case WEEK:
                    map.setStartDate(map.getStatDate());
                    map.setEndDate(DateUtil.formatDate(DateUtil.offsetDay(DateUtil.parse(map.getStatDate()), 6)));
                    break;
                case MONTH:
                    map.setStartDate(map.getStatDate() + "-01");
                    map.setEndDate(DateUtil.formatDate(DateUtil.offsetDay(DateUtil.offsetMonth(DateUtil.parse(map.getStatDate() + "-01"), 1), -1)));
                    break;
                default:
                    break;
            }
            if (voiceOverviewListBO.getRoomCategoryId() == null) {
                map.setRoomCategory("/");
            } else {
                map.setRoomCategory(roomCategoriesMap.get(voiceOverviewListDTO.getRoomCategoryId() + ""));
            }
            return map;
        }).collect(Collectors.toList());
    }

    public void export(VoiceOverviewListDTO dto) {
        String fileName = "语言互动-业务总览";
        LinkedHashMap<String, Mapper<VoiceOverviewVO>> map = new LinkedHashMap<>();
        QueryTypeStatusEnum anEnum = QueryTypeStatusEnum.getEnum(dto.getQueryType());
        switch (anEnum) {
            case DAY:
                map.put("日期", v -> v.getStartDate());
                break;
            default:
                map.put("日期", v -> v.getStartDate() + "-" + v.getEndDate());
                break;
        }
        map.put("房间类型", v -> v.getRoomCategory());
        map.put("钻石消费", v -> v.getVirtualMoneyAll().toString());
        map.put("消费人数", v -> v.getConsumeUserNum() + "");
        map.put("消费次数", v -> v.getConsumeNum() + "");
        map.put("魅力值流水", v -> v.getCharmMoney().toString());
        map.put("进厅人数", v -> v.getEnterRoomUserNum() + "");
        map.put("进厅次数", v -> v.getEnterRoomNum() + "");
        map.put("新增收藏", v -> v.getAddCollectNum() + "");
        map.put("新增关注", v -> v.getAddFollowNum() + "");
        map.put("用户平均停留时长", v -> v.getUserStayTimeAvg() + "");
        map.put("停留>5分钟用户数", v -> v.getStayFiveMinUserNum() + "");
        map.put("互动用户数", v -> v.getInteractUserNum() + "");
        Querier querier = (num) -> {
            List<VoiceOverviewVO> list = list(dto);
            PageInfo pageInfo = new PageInfo(list);
            pageInfo.setHasNextPage(false);
            return pageInfo;
        };
        CsvExportUtil.export(100, fileName, map, querier);
    }
}
